package com.netcracker.studportal.server.facade;

import java.io.File;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.log4j.Logger;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

import com.netcracker.studportal.server.model.Exam;
import com.netcracker.studportal.server.model.ExamWithResult;
import com.netcracker.studportal.server.model.Material;
import com.netcracker.studportal.server.model.Professor;
import com.netcracker.studportal.server.model.Student;
import com.netcracker.studportal.server.model.Subject;
import com.netcracker.studportal.server.util.FacadeUtil;
import com.netcracker.studportal.server.util.FactoryDAO;
import com.netcracker.studportal.server.util.FileUtil;

public class FacadeStudent {
	private static final Logger LOG = Logger.getLogger(FacadeStudent.class);
	
	/**
	 * Method for getting list of exams for student.
	 * 
	 * @param param 
	 * 	JSONObject in format:
	 * 	"student_id" : "value"
	 * 
	 * @return
	 *  JSONArray of JSONObject in format:
	 *  "exam_id" 		: "value",
	 *  "student_id" 	: "value",
	 *  "mark" 			: "value",
	 *  "note" 			: "value",
	 *  "exam" 			: JSONObject in format:
	 *  				    "exam_id" 			: "value",
	 *  					"subject_id" 		: "value",
	 * 						"subject_name" 		: "value",
	 * 						"exam_date" 		: "value",
	 * 						"type"              : "value",
	 * 						"prof_id" 			: "value",
	 * 						"prof_first_name" 	: "value",
	 * 						"patronymic" 		: "value",
	 * 						"prof_last_name" 	: "value";
	 * 
	 * In case of errors:
	 * 	JSONObject in format:
	 *  "error" 		: "error_message",
	 *  "stacktrace" 	: "error_stacktrace";
	 */
	public String getExamsByStudent(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'getExamsByStudent' called with parameters = " + param);
		}
		
		try {
			Map<String, String> inputParams = FacadeUtil.extractInputParams(param, new String[]{"student_id"});
			
			Long studentID = Long.parseLong(inputParams.get("student_id"));
			
			Student student = FactoryDAO.getStudentDAO().getById(studentID);	
				
			if(student == null) {
				throw new Exception("Student with student_id = " + studentID + " is not found!");
			}
				
			List<ExamWithResult> exams = student.getExamWithResult();
			if(exams != null && exams.size() > 0) {
				JSONArray list = new JSONArray();
				for(ExamWithResult e : exams) {
					list.add(e.kJSON());
				}	
				String result = list.toString();
				
				return result;
			} else {
				// return empty JSON array, because student doesn't have any exams
				return new JSONArray().toString();
			}
		} catch (Exception e) {
			LOG.error("Error: ", e);
			JSONObject obj = new JSONObject();
			obj.put("error", e.getMessage());
			obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				
			return obj.toString();
		}
	}
	
	/**
	 * Method for getting subject for exam.
	 * 
	 * @param param
	 *  JSONObject in format:
	 * 	"exam_id" : "value"
	 * 
	 * @return
	 * 	JSONObject in format:
	 *  "subject_id" : "value",
	 *  "name"       : "value",
	 *  "hours"      : "value",
	 *  "course"     : "value",
	 *  "description": "value";
	 * 
	 * In case of errors:
	 * 	JSONObject in format:
	 *  "error" 		: "error_message",
	 *  "stacktrace" 	: "error_stacktrace";
	 */
	public String getSubjectByExam(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'getSubjectByExam' called with parameters = " + param);
		}
		
		try {
			Map<String, String> inputParams = FacadeUtil.extractInputParams(param, new String[]{"exam_id"});
				
			Long examID = Long.parseLong(inputParams.get("exam_id"));
				
			Exam exam=FactoryDAO.getExamDAO().getById(examID);
				
			if(exam==null) throw new Exception("Exam with exam_id = " + examID + " is not found!");
					
			Subject subj=exam.getSubject();
			String result = null;
			if(subj != null)
				result=subj.kJSON().toString();
			else {
				throw new RuntimeException("Subject for exam with exam_id = " + examID + " is not found!");
			}
				
			return result;								 
		} catch (Exception e) {
			LOG.error("Error: ", e);
			JSONObject obj = new JSONObject();
			obj.put("error", e.getMessage());
			obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
			
			return obj.toString();
		}
	}
	
	/**
	 * Method for getting list of materials for exam.
	 * 
	 * @param param
	 *  JSONObject in format:
	 *  "exam_id" : "value"
	 * 
	 * @return 
	 * 	JSONArray of JSONObject in format:
	 *  "material_id" 	: "value",
	 *  "exam_id" 		: "value",
	 *  "material_name" : "value",
	 * 
	 * In case of errors:
	 * 	JSONObject in format:
	 *  "error" 		: "error_message",
	 *  "stacktrace" 	: "error_stacktrace";
	 */
	public String getMaterialsByExam(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'getMaterialsByExam' called with parameters = " + param);
		}

		try {
			Map<String, String> inputParams = FacadeUtil.extractInputParams(param, new String[]{"exam_id"});
				
			Long examID = Long.parseLong(inputParams.get("exam_id"));
				
			Exam ex=new Exam();
			ex.setId(examID);
			List<Material> materials=(List<Material>) FactoryDAO.getMaterialDAO().getMaterialsByExam(ex);
						
			if(materials != null && materials.size() > 0) {
				JSONArray list = new JSONArray();
				for(Material m : materials) {
					JSONObject json = m.kJSON();
					list.add(json);
				}
					
				String result = list.toString();
				return result;
			} else {
				// return empty JSON array, because exam doesn't have any materials
				return new JSONArray().toString();
			}
		} catch (Exception e) {
			LOG.error("Error: ", e);
			JSONObject obj = new JSONObject();
			obj.put("error", e.getMessage());
			obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
			
			return obj.toString();
		}
	}
	
	/**
	 * Method for getting proffesor for exam.
	 * 
	 * @param param
	 *  JSONObject in format:
	 *  "exam_id" : "value"
	 * 
	 * @return
	 * 	JSONObject in format:
	 *  "prof_id" 		: "value",
	 *  "first_name" 	: "value",
	 *  "patronymic" 	: "value",
	 *  "last_name" 	: "value",
	 *  "birthday" 		: "value",
	 *  "note" 			: "value",
	 *  "univ_id" 		: "value",
	 *  "univ_name" 	: "value",
	 *  "city" 			: "value";
	 * 
	 * In case of errors:
	 * 	JSONObject in format:
	 *  "error" 		: "error_message",
	 *  "stacktrace" 	: "error_stacktrace";
	 */
	public String getProfByExam(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'getProfByExam' called with parameters = " + param);
		}
		
		try {
			Map<String, String> inputParams = FacadeUtil.extractInputParams(param, new String[]{"exam_id"});
			
			Long examID = Long.parseLong(inputParams.get("exam_id"));
			
			Exam ex=new Exam();
			ex.setId(examID);
			Professor prof=FactoryDAO.getProfessorDAO().getProfessorsByExam(ex);
				
			if(prof==null) {
				throw new Exception("Professor for exam with exam_id = '" + examID + "' is not found!");
			}
				
			String result = prof.kJSON().toString();
			
			return result;
		} catch (Exception e) {
			LOG.error("Error: ", e);
			JSONObject obj = new JSONObject();
			obj.put("error", e.getMessage());
			obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
				e.printStackTrace();
			return obj.toString();
		}
	}
	
	
	
	/**
	 * Method for getting list of materials for exam.
	 * 
	 * @param param
	 *  JSONObject in format:
	 *  "material_id" : "value"
	 * 
	 * @return 
	 * 	JSONObject in format:
	 *  "file_name" 	: "value",
	 *  "file_content" 	: "value";
	 * 
	 * 
	 * In case of errors:
	 * 	JSONObject in format:
	 *  "error" 		: "error_message",
	 *  "stacktrace" 	: "error_stacktrace";
	 */
	public String loadMaterialByID(String param) {
		if (LOG.isDebugEnabled()) {
			LOG.debug("Method 'loadMaterialByID' called with parameters = " + param);
		}

		try {
			Map<String, String> inputParams = FacadeUtil.extractInputParams(param, new String[]{"material_id"});
				
			Long materialID = Long.parseLong(inputParams.get("material_id"));
		
			Material material=FactoryDAO.getMaterialDAO().getById(materialID);
			
			if(material == null) {
				throw new Exception("Material with material_id = " + materialID + " is not found!");
			}

			String pathToFile = material.getPath();
			if(StringUtils.isNotEmpty(pathToFile)) {
				JSONObject mjson = new JSONObject();
				
				String fileName = new File(pathToFile).getName();
				mjson.put("file_name", fileName);
					
				String encodedFile = FileUtil.loadAndEncodeFile(pathToFile);
				mjson.put("file_content", encodedFile);
						
				return mjson.toJSONString();
			} else {
				throw new RuntimeException("Path to file with material = " + materialID + " is empty!");
			}
		} catch (Exception e) {
			LOG.error("Error: ", e);
			JSONObject obj = new JSONObject();
			obj.put("error", e.getMessage());
			obj.put("stacktrace", ExceptionUtils.getFullStackTrace(e));
			
			return obj.toString();
		}
	}
}
